package com.gopay.common.trace.aop;

import com.gopay.common.trace.GopayTracerType;
import com.gopay.common.trace.anotation.GopayTracer;
import com.gopay.common.trace.helper.LogAbstractHelper;
import com.gopay.common.trace.helper.LogAllOrderAopHelper;
import com.gopay.common.trace.helper.LogLocalHelper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.aop.support.AopUtils;
import org.springframework.stereotype.Component;

/**
 * 方法追踪切面，实现方法
 * @author  zyt on 2017/11/30.
 */
@Aspect
@Component
public class GopayTracerAspect {

    /**
     * 注解切面
     */
    @Pointcut("@annotation(com.gopay.common.trace.anotation.GopayTracer)")
    public void annotationPointCut() {
    }


    /***
     * 环绕通知
     * @param joinPoint
     * @param gopayTracer
     * @return
     * @throws Throwable
     */
    @Around(value = "annotationPointCut() && @annotation(gopayTracer)")
    public Object around(ProceedingJoinPoint joinPoint, GopayTracer gopayTracer) throws Throwable{
        Object obj;
        switch (gopayTracer.tracerType())
        {
            case GopayTracerType.TIME_TRACE:{
                obj = timerTracerAround(joinPoint, gopayTracer);
                break;
            }
            case GopayTracerType.ORDER_TRACE:{
                obj = orderTracerAround(joinPoint, gopayTracer);
                break;
            }
            default:{
                obj = defaultTracerAround(joinPoint, gopayTracer);
                break;
            }
        }

        return obj;
    }


    /**
     * 方法切面
     * @param joinPoint
     * @param gopayTracer
     * @return
     * @throws Throwable
     */
    private Object timerTracerAround(ProceedingJoinPoint joinPoint, GopayTracer gopayTracer) throws Throwable{
        Object obj;
        boolean isProxy = AopUtils.isAopProxy(joinPoint.getTarget());

        //如果是代理访问 则直接执行
        if (isProxy) {
            return joinPoint.proceed();
        }

        LogAbstractHelper helper = new LogLocalHelper();
        //Map<String, String> valueMap = new HashMap<String, String>();

        helper.beforeT(joinPoint, gopayTracer);
        try {
            obj = joinPoint.proceed();
        } catch (Throwable throwable) {
            helper.exT(throwable);
            throw  throwable;
        } finally {
            helper.afterT(joinPoint, gopayTracer);
        }
        return obj;
    }

    /**
     * 订单 处理
     * @param joinPoint
     * @param gopayTracer
     * @return
     * @throws Throwable
     */
    private Object orderTracerAround(ProceedingJoinPoint joinPoint, GopayTracer gopayTracer) throws Throwable{
        Object returnValue;
        LogAbstractHelper helper = new LogAllOrderAopHelper();
        try {
            helper.beforeT();

            returnValue = joinPoint.proceed();

        } catch (Throwable e) {
            helper.exT(e);
            throw e;
        } finally {
            helper.afterT(joinPoint, gopayTracer);
        }
        return returnValue;
    }

    /**
     * 默认类型 通知==> 目前不会走到这个分支
     * @param joinPoint
     * @param gopayTracer
     * @return
     * @throws Throwable
     */
    private Object defaultTracerAround(ProceedingJoinPoint joinPoint, GopayTracer gopayTracer) throws Throwable{
        return joinPoint.proceed();
    }

}
